home *** CD-ROM | disk | FTP | other *** search
/ CU Amiga Super CD-ROM 25 / CU Amiga Magazine's Super CD-ROM 25 (1998)(EMAP Images)(GB)(Track 1 of 2)[!][issue 1998-08].iso / CUCD / Programming / QuakeTools / src / libqtools / graphics.c < prev    next >
Encoding:
C/C++ Source or Header  |  1998-06-11  |  18.6 KB  |  667 lines

  1. #define    LIBQTOOLS_CORE
  2. #include "../include/libqtools.h"
  3. #ifdef HAVE_LIBPNG
  4. #include <png.h>
  5. #endif
  6. #ifdef HAVE_LIBJPEG
  7. #include <jpeglib.h>
  8. #endif
  9.  
  10. bool dither = FALSE;
  11. short int dithervalue = 16;
  12. bool smoothing = FALSE;
  13. short int smoothingvalue = 2;
  14. short int smoothingshift = 1;
  15.  
  16. //#define FS_SCALE 16
  17. #define FS_SCALE dithervalue
  18. //#define S_SCALE 2
  19. #define S_SCALE smoothingvalue
  20. //#define S_SHIFT 2
  21. #define S_SHIFT smoothingshift
  22.  
  23. typedef    float        PRECISION;
  24. typedef    float        PRECISION_EXT;
  25.  
  26. struct drgb {
  27.   PRECISION r, g, b;
  28. };
  29.  
  30. static inline unsigned char MatchD(register struct drgb *rawpix, register struct rgb *Palette) {
  31.   struct rgb newpix;
  32.   newpix.r = (unsigned char)rawpix->r;
  33.   newpix.g = (unsigned char)rawpix->g;
  34.   newpix.b = (unsigned char)rawpix->b;
  35.   return Match(&newpix, Palette);
  36. }
  37.  
  38. /*
  39.  * picture-tools
  40.  */
  41.  
  42. bool RemapPalettes(unsigned char *dataBody, int dataSize, struct rgb *oldPalette, struct rgb *newPalette) {
  43.   unsigned char *conversionArray;
  44.   
  45.   if((conversionArray = (unsigned char *)tmalloc(256))) {
  46.     int i;
  47.     
  48.     for(i = 0; i < 256; i++)
  49.       conversionArray[i] = Match(&oldPalette[i], &newPalette[i]);
  50.     for(i = 0; i < dataSize; i++)
  51.       dataBody[i] = conversionArray[dataBody[i]];
  52.     
  53.     tfree(conversionArray);
  54.     return TRUE;
  55.   }
  56.   else
  57.     return FALSE;
  58. }
  59.  
  60. #ifdef HAVE_LIBPNG
  61. #ifdef REPLACE_STDIO
  62. void png_default_read_data(png_structp png_ptr, png_bytep data, png_size_t length) {
  63.   if (fread(data, (png_size_t)1, length, (FILE *)png_ptr->io_ptr) != length)
  64.     png_error(png_ptr, "Read Error");
  65. }
  66.  
  67. void png_default_write_data(png_structp png_ptr, png_bytep data, png_size_t length) {
  68.   if (fwrite(data, 1, length, (FILE *)(png_ptr->io_ptr)) != length)
  69.     png_error(png_ptr, "Write Error");
  70. }
  71. #endif
  72.  
  73. bool SavePNG(register FILE *imgFile, register struct palpic *Picture) {
  74.   png_struct *png_ptr;
  75.   png_info *info_ptr;
  76.   bool retval = FALSE;
  77.  
  78.   if((png_ptr = png_create_write_struct(PNG_LIBPNG_VER_STRING, 0, 0, 0))) {
  79.     if((info_ptr = png_create_info_struct(png_ptr))) {
  80.       if (!setjmp(png_ptr->jmpbuf)) {
  81.         short int y;
  82.         png_byte *row_pointers = (png_byte *)Picture->rawdata;
  83.      
  84.         png_init_io(png_ptr, imgFile);
  85.     png_set_IHDR(png_ptr, info_ptr, Picture->width, Picture->height, 8, PNG_COLOR_TYPE_PALETTE,
  86.              PNG_INTERLACE_NONE, PNG_COMPRESSION_TYPE_BASE, PNG_FILTER_TYPE_BASE);
  87.     png_set_PLTE(png_ptr, info_ptr, (png_color *)Picture->palette, 256);
  88.     png_set_compression_level (png_ptr, 9);
  89.     png_write_info(png_ptr, info_ptr);
  90.     png_set_packing (png_ptr);
  91.         for (y = 0; y < Picture->height; y++) {
  92.           png_write_rows(png_ptr, &row_pointers, 1);
  93.           row_pointers += Picture->width;
  94.         }
  95.         png_write_end(png_ptr, info_ptr);
  96.         retval = TRUE;
  97.       }
  98.       else
  99.         eprintf("cannot set png-jump\n");
  100.     }
  101.     else
  102.       eprintf("cannot create info-struct\n");
  103.  
  104.     png_destroy_write_struct(&png_ptr, 0);
  105.   }
  106.   else
  107.     eprintf("cannot create png-struct\n");
  108.   
  109.   return retval;
  110. }
  111. #endif
  112. #ifdef HAVE_LIBJPEG
  113. bool SaveJPEG(register FILE *imgFile, register unsigned char *rawBody, register short int width, register short int height) {
  114.   struct jpeg_compress_struct cinfo;
  115.   struct jpeg_error_mgr jerr;
  116.   unsigned char *row_pointers = rawBody;
  117.  
  118.   cinfo.err = jpeg_std_error(&jerr);
  119.   jpeg_create_compress(&cinfo);
  120.   jpeg_stdio_dest(&cinfo, imgFile);
  121.  
  122.   cinfo.image_width = width;         /* image width and height, in pixels */
  123.   cinfo.image_height = height;
  124.   cinfo.input_components = 3;        /* # of color components per pixel */
  125.   cinfo.in_color_space = JCS_RGB;     /* colorspace of input image */
  126.  
  127.   jpeg_set_defaults(&cinfo);
  128.  
  129.   cinfo.dct_method = JDCT_FLOAT;
  130.   cinfo.optimize_coding = TRUE;
  131.  
  132.   jpeg_set_quality(&cinfo, 100, TRUE);
  133.   jpeg_start_compress(&cinfo, TRUE);
  134.   while (cinfo.next_scanline < cinfo.image_height) {
  135.     jpeg_write_scanlines(&cinfo, &row_pointers, 1);
  136.     row_pointers += (width * 3);
  137.   }
  138.  
  139.   jpeg_finish_compress(&cinfo);
  140.   jpeg_destroy_compress(&cinfo);
  141.   
  142.   return TRUE;
  143. }
  144. #endif
  145.  
  146. bool PutImage(FILE *file, struct palpic *Picture, filetype picType) {
  147.   bool retval = FALSE;
  148.  
  149.   switch (picType) {
  150.     case TYPE_PPM:
  151. #ifdef HAVE_LIBJPEG
  152.     case TYPE_JPEG:
  153. #endif
  154.       {
  155.         short int x = Picture->width, y = Picture->height;
  156.         struct rgb *PPMPic = (struct rgb *)tmalloc(x * y * 3);
  157.  
  158.         if (PPMPic) {
  159.           unsigned char *bodySrc = Picture->rawdata;
  160.           struct rgb *bodyPal = Picture->palette;
  161.           struct rgb *bodyDst = PPMPic;
  162.  
  163.           /*
  164.            * put header 
  165.            */
  166.           fprintf(file, "P6\n%d %d\n255\n", Picture->width, Picture->height);
  167.           /*
  168.            * convert body 
  169.            */
  170.           for (y = 0; y < Picture->width; y++) {
  171.             for (x = 0; x < Picture->height; x++) {
  172.           *bodyDst++ = bodyPal[(short int)(*bodySrc++)];
  173.             }
  174.           }
  175.  
  176.           if(picType == TYPE_PPM) {
  177.             /*
  178.              * put body 
  179.              */
  180.             fwrite(PPMPic, 1, (Picture->width * Picture->height * 3), file);
  181.             tfree(PPMPic);
  182.             retval = TRUE;
  183.           }
  184. #ifdef HAVE_LIBJPEG
  185.       else
  186.         retval = SaveJPEG(file, (unsigned char *)PPMPic, Picture->width, Picture->height);
  187. #endif
  188.         }
  189.         else
  190.           eprintf("cannot tmalloc %d bytes ppm-body\n", x * y * 3);
  191.       }
  192.       break;
  193. #ifdef HAVE_LIBPNG
  194.     case TYPE_PNG:
  195.       retval = SavePNG(file, Picture);
  196.       break;
  197. #endif
  198.     default:
  199.       eprintf("unknown picture-type\n");
  200.       break;
  201.   }
  202.  
  203.   return retval;
  204. }
  205.  
  206. #define CHECK_SIZE    12
  207.  
  208. filetype CheckImage(register FILE *imgFile) {
  209.   union blabla {
  210.     char minChars[CHECK_SIZE];
  211.     int minInts[CHECK_SIZE / 4];
  212.   } minHeader;
  213.  
  214.   fseek(imgFile, 0, SEEK_SET);
  215.   fread(&minHeader, 1, CHECK_SIZE, imgFile);
  216.   fseek(imgFile, 0, SEEK_SET);
  217. #ifdef HAVE_LIBPNG
  218.   if((minHeader.minInts[0] == 0x89504E47) && (minHeader.minInts[1] == 0x0D0A1A0A))
  219.     return TYPE_PNG;
  220. #endif
  221. #ifdef HAVE_LIBJPEG
  222.   if((minHeader.minInts[0] == 0xFFD8FFE0) && (minHeader.minInts[1] == 0x00104A46))
  223.     return TYPE_JPEG;
  224. #endif
  225. #ifdef ILBM
  226.   if (minHeader.minInts[0] == 0x464F524D) && (minHeader.minInts[2] == 0x494C424D))
  227.     return TYPE_ILBM;
  228. #endif
  229.   if((minHeader.minChars[0] == 'P') && (minHeader.minChars[1] == '6') && (minHeader.minChars[2] == '\n'))
  230.     return TYPE_PPM;
  231.   if((minHeader.minChars[0] == 'P') && (minHeader.minChars[1] == '5') && (minHeader.minChars[2] == '\n'))
  232.     return TYPE_PGM;
  233.  
  234.   return TYPE_NONE;
  235. }
  236.  
  237. #ifdef HAVE_LIBPNG
  238. filetype LoadPNG(register FILE *imgFile, register struct rgb **bodySrc, register short int *width, register short int *height) {
  239.   png_struct *png_ptr;
  240.   png_info *info_ptr;
  241.   short int color_type = 0;
  242.    
  243.   if((png_ptr = png_create_read_struct(PNG_LIBPNG_VER_STRING, 0, 0, 0))) {
  244.     if((info_ptr = png_create_info_struct(png_ptr))) {
  245.       if (!setjmp(png_ptr->jmpbuf)) {
  246.         short int number_passes, pass, y;
  247.       
  248.         png_init_io(png_ptr, imgFile);
  249.         png_read_info(png_ptr, info_ptr);
  250.         
  251.         *width = info_ptr->width;
  252.         *height = info_ptr->height;
  253.         color_type = info_ptr->color_type;
  254.         
  255.         if((*bodySrc = (struct rgb *)tmalloc((*width) * (*height) * 3))) {
  256.           png_byte *row_pointers = (png_byte *)(*bodySrc);
  257.         
  258.           if ((color_type == PNG_COLOR_TYPE_PALETTE) || ((color_type == PNG_COLOR_TYPE_GRAY) && (info_ptr->bit_depth < 8)))
  259.             png_set_expand(png_ptr);
  260.           
  261.           number_passes = png_set_interlace_handling(png_ptr);
  262.           png_read_update_info(png_ptr, info_ptr);
  263.           for (pass = 0; pass < number_passes; pass++) {
  264.             for (y = 0; y < (*height); y++) {
  265.               png_read_rows(png_ptr, &row_pointers, 0, 1);
  266.               if(color_type == PNG_COLOR_TYPE_GRAY)
  267.                 row_pointers += ((*width));
  268.               else
  269.                 row_pointers += ((*width) * 3);
  270.             }
  271.           }
  272.         }
  273.         else
  274.           eprintf("cannot tmalloc %d bytes for picture\n", (*width) * (*height) * 3);
  275.         
  276.         png_read_end(png_ptr, info_ptr);
  277.       }
  278.       else
  279.         eprintf("cannot set png-jump\n");
  280.       
  281.       png_destroy_read_struct(&png_ptr, &info_ptr, 0);
  282.     }
  283.     else {
  284.       png_destroy_read_struct(&png_ptr, 0, 0);
  285.       eprintf("cannot create info-struct\n");
  286.     }
  287.   }
  288.   else
  289.     eprintf("cannot create png-struct\n");
  290.   
  291.   if(color_type == PNG_COLOR_TYPE_GRAY)
  292.     return TYPE_PGM;
  293.   else if(color_type)
  294.     return TYPE_PPM;
  295.   else
  296.     return TYPE_NONE;
  297. }
  298. #endif
  299. #ifdef HAVE_LIBJPEG
  300. filetype LoadJPEG(register FILE *imgFile, register struct rgb **bodySrc, register short int *width, register short int *height) {
  301.   struct jpeg_decompress_struct cinfo;
  302.   struct jpeg_error_mgr jerr;
  303.  
  304.   cinfo.err = jpeg_std_error(&jerr);
  305.   jpeg_create_decompress(&cinfo);
  306.   jpeg_stdio_src(&cinfo, imgFile);
  307.   jpeg_read_header(&cinfo, TRUE);
  308.  
  309.   cinfo.dct_method = JDCT_FLOAT;
  310.   cinfo.out_color_space = JCS_RGB;
  311.   
  312.   jpeg_start_decompress(&cinfo);
  313.  
  314.   *width = (short int)cinfo.image_width;
  315.   *height = (short int)cinfo.image_height;
  316.  
  317.   if((*bodySrc = (struct rgb *)tmalloc(cinfo.image_width * cinfo.image_height * 3))) {
  318.     unsigned char *row_pointers = (unsigned char *)(*bodySrc);
  319.     
  320.     while (cinfo.output_scanline < cinfo.output_height) {
  321.       jpeg_read_scanlines(&cinfo, &row_pointers, 1);
  322.       row_pointers += (cinfo.image_width * 3);
  323.     }
  324.   }
  325.   else
  326.     eprintf("cannot tmalloc %d bytes for picture\n", cinfo.image_width * cinfo.image_height * 3);
  327.  
  328.   jpeg_finish_decompress(&cinfo);
  329.   jpeg_destroy_decompress(&cinfo);
  330.   return TYPE_PPM;
  331. }
  332. #endif
  333.  
  334. struct rgb *LoadImage(register FILE *imgFile, register filetype *picType, register short int *width, register short int *height) {
  335.   struct rgb *bodySrc = 0;
  336.   int x, y;
  337.   
  338.   switch (*picType) {
  339. #ifdef HAVE_LIBPNG
  340.     case TYPE_PNG:
  341.       *picType = LoadPNG(imgFile, (struct rgb **)&bodySrc, width, height);
  342.       break;
  343. #endif
  344. #ifdef HAVE_LIBJPEG
  345.     case TYPE_JPEG:
  346.       *picType = LoadJPEG(imgFile, (struct rgb **)&bodySrc, width, height);
  347.       break;
  348. #endif
  349. #ifdef ILBM
  350.     case TYPE_ILBM:
  351.       break;
  352. #endif
  353.     case TYPE_PPM:
  354.       fscanf(imgFile, "P6\n%d %d\n255\n", &x, &y);
  355.       *width = (short int)x;
  356.       *height = (short int)y;
  357.       if((bodySrc = (struct rgb *)tmalloc(x * y * 3)))
  358.         fread(bodySrc, 1, x * y * 3, imgFile);
  359.       else
  360.         eprintf("cannot tmalloc %d bytes for picture\n", x * y * 3);
  361.       break;
  362.     case TYPE_PGM:
  363.       fscanf(imgFile, "P5\n%d %d\n255\n", &x, &y);
  364.       *width = (short int)x;
  365.       *height = (short int)y;
  366.       if((bodySrc = (struct rgb *)tmalloc(x * y)))
  367.         fread(bodySrc, 1, x * y, imgFile);
  368.       else
  369.         eprintf("cannot tmalloc %d bytes for picture\n", x * y);
  370.       break;
  371.     default:
  372.       eprintf("unknown picture-type\n");
  373.       break;
  374.   }
  375.   
  376.   return bodySrc;
  377. }
  378.  
  379. struct palpic *GetImage(FILE *file, char *picName, short int alignX, short int alignY) {
  380.   struct palpic *Picture = 0;
  381.   struct rgb *bodySrc;
  382.   struct drgb *bodyTmp;
  383.   short int width, height;
  384.   filetype picType = TYPE_NONE;
  385.  
  386.   if(smoothing == TRUE)
  387.     switch(S_SCALE) {
  388.       case 1:
  389.         S_SHIFT = 0;
  390.         break;
  391.       case 2:
  392.         S_SHIFT = 1;
  393.         break;
  394.       case 4:
  395.         S_SHIFT = 2;
  396.         break;
  397.       case 8:
  398.         S_SHIFT = 3;
  399.         break;
  400.       case 16:
  401.         S_SHIFT = 4;
  402.         break;
  403.       default:
  404.         S_SHIFT = -1;
  405.         break;
  406.     }
  407.  
  408.   if((picType = CheckImage(file)) != TYPE_NONE) {
  409.     if((bodySrc = LoadImage(file, &picType, &width, &height))) {
  410.       short int newwidth = width, newheight = height;
  411.  
  412.       /*
  413.        * calculate a new size that is multiple of align or an absolute value
  414.        */
  415.       if (alignX > 0) {
  416.         if ((width % alignX))
  417.           newwidth = width - (width % alignX) + alignX;
  418.       }
  419.       else
  420.         newwidth = -alignX;
  421.       if (alignY > 0) {
  422.         if ((height % alignY))
  423.           newheight = height - (height % alignY) + alignY;
  424.       }
  425.       else
  426.         newheight = -alignY;
  427.  
  428.       if ((dither == FALSE) || ((dither == TRUE) && (bodyTmp = (struct drgb *)tmalloc(newwidth * newheight * 3 * sizeof(PRECISION))))) {
  429.         if ((Picture = pmalloc(newwidth, newheight, 0, picName))) {
  430.       double dx = (double)width / newwidth;
  431.       double dy = (double)height / newheight;
  432.       double x, y;
  433.       short int nx, ny;
  434.       struct rgb *Palette = Picture->palette;
  435.       unsigned char *flowDst = Picture->rawdata;
  436.       struct drgb *flowTmp = bodyTmp;
  437.       
  438. #ifdef DEBUG
  439.       mprintf("size; %dx%d, newsize: %dx%d, diffs: %fx%f\n", width, height, newwidth, newheight, dx, dy);
  440. #endif
  441.       /*
  442.        * scale body in advance of dithering 
  443.        */
  444.       for (ny = 0, y = 0; ny < newheight; ny++, y += dy) {
  445.         for (nx = 0, x = 0; nx < newwidth; nx++, x += dx) {
  446.           struct rgb rawpix;
  447. #define    floatPos(yy, xx)    (((int)(yy) * width) + (int)xx)
  448.  
  449.           /*
  450.            * get unscaled value 
  451.            */
  452.           if (picType == TYPE_PPM) {
  453.             /*
  454.              * colored ppm 
  455.              */
  456.             rawpix = bodySrc[floatPos(y, x)];
  457.             
  458.             if (smoothing == TRUE) {
  459.               short int sR = 0, sG = 0, sB = 0, sS = 0;
  460.  
  461. #define AddRGB(pospos) ({ \
  462.   struct rgb *addpix = &bodySrc[pospos]; \
  463.   sR += (short int)addpix->r; \
  464.   sG += (short int)addpix->g; \
  465.   sB += (short int)addpix->b; \
  466.   sS++; })
  467.  
  468.           /*
  469.            * smoothing means
  470.            * 123
  471.            * 4a5 a += ((a-((1+2+3+4+5+6+7+8)/8))/smoothing)
  472.            * 678
  473.            */
  474.               if((y - 1) > 0) {
  475.                 if((x - 1) > 0)
  476.                   AddRGB(floatPos(y - 1, x - 1));        //2
  477.                 AddRGB(floatPos(y - 1, x));            //1
  478.                 if((x + 1) < width)
  479.                   AddRGB(floatPos(y - 1, x + 1));        //3
  480.               }
  481.               if((x - 1) > 0)
  482.                 AddRGB(floatPos(y, x - 1));            //4
  483.               AddRGB(floatPos(y, x));            //a
  484.               if((x + 1) < width)
  485.                 AddRGB(floatPos(y, x + 1));            //5
  486.               if((y + 1) < height) {
  487.                 if((x - 1) > 0)
  488.                   AddRGB(floatPos(y + 1, x - 1));        //7
  489.                 AddRGB(floatPos(y + 1, x));            //6
  490.                 if((x + 1) < width)
  491.                   AddRGB(floatPos(y + 1, x + 1));        //8
  492.               }
  493.             
  494.               sR /= sS;
  495.               sG /= sS;
  496.               sB /= sS;
  497.  
  498. #define SetRGB(src, dst) ({ \
  499.   src -= (short int)rawpix.dst; \
  500.   src = S_SHIFT >= 0 ? (src >> S_SHIFT) : (src / S_SCALE); \
  501.   if(src) { \
  502.     src += (short int)rawpix.dst; \
  503.     if(src > 255) \
  504.       src = 255; \
  505.     else if(src < 0) \
  506.       src = 0; \
  507.     rawpix.dst = (unsigned char)src; } })
  508.     
  509.           SetRGB(sR, r);
  510.           SetRGB(sG, g);
  511.           SetRGB(sB, b);
  512.             }
  513.           }
  514.           else if (picType == TYPE_PGM) {
  515.             /*
  516.              * gray    pgm 
  517.              */
  518.             rawpix.r = ((unsigned char *)bodySrc)[floatPos(y, x)];
  519.             
  520.             if (smoothing == TRUE) {
  521.               short int sG = 0, sS = 0;
  522.  
  523. #define AddGrey(pospos) ({ \
  524.   sG += (short int)(((unsigned char *)bodySrc)[pospos]); \
  525.   sS++; })
  526.  
  527.           /*
  528.            * smoothing means
  529.            * 123
  530.            * 4a5 a += ((a-((1+2+3+4+5+6+7+8)/8))/smoothing)
  531.            * 678
  532.            */
  533.               if((y - 1) > 0) {
  534.                 if((x - 1) > 0)
  535.                   AddGrey(floatPos(y - 1, x - 1));    //2
  536.                 AddGrey(floatPos(y - 1, x));    //1
  537.                 if((x + 1) < width)
  538.                   AddGrey(floatPos(y - 1, x + 1));    //3
  539.               }
  540.               if((x - 1) > 0)
  541.                 AddGrey(floatPos(y, x - 1));    //4
  542.               AddGrey(floatPos(y, x));        //a
  543.               if((x + 1) < width)
  544.                 AddGrey(floatPos(y, x + 1));    //5
  545.               if((y + 1) < height) {
  546.                 if((x - 1) > 0)
  547.                   AddGrey(floatPos(y + 1, x - 1));    //7
  548.                 AddGrey(floatPos(y + 1, x));    //6
  549.                 if((x + 1) < width)
  550.                   AddGrey(floatPos(y + 1, x + 1));    //8
  551.               }
  552.             
  553.               sG /= sS;
  554.  
  555. #define SetGrey(src, dst) ({ \
  556.   src -= (short int)rawpix.dst; \
  557.   src = S_SHIFT >= 0 ? (src >> S_SHIFT) : (src / S_SCALE); \
  558.   if(src) { \
  559.     src += (short int)rawpix.dst; \
  560.     if(src > 255) \
  561.       src = 255; \
  562.     else if(src < 0) \
  563.       src = 0; \
  564.     rawpix.dst = (unsigned char)src; }})
  565.     
  566.           SetGrey(sG, r);
  567.             }
  568.             
  569.         rawpix.b = rawpix.g = rawpix.r;
  570.           }
  571.  
  572.           if (dither == TRUE) {
  573.             /*
  574.              * put scaled value 
  575.              */
  576.             *((PRECISION *)flowTmp)++ = (PRECISION)rawpix.r;
  577.             *((PRECISION *)flowTmp)++ = (PRECISION)rawpix.g;
  578.             *((PRECISION *)flowTmp)++ = (PRECISION)rawpix.b;
  579.           }
  580.           else {
  581.             /*
  582.              * put scaled value 
  583.              */
  584.             *flowDst++ = Match(&rawpix, Palette);
  585. #ifdef DEBUG
  586.             mprintf("pixel %dx%d: %02x%02x%02x matches %02x (%02x%02x%02x) with match %d\n", ny, nx, rawpix.r, rawpix.g, rawpix.b, palpix, Palette[palpix].r, Palette[palpix].g, Palette[palpix].b, match);
  587. #endif
  588.           }
  589.         }
  590.         mprogress((int)newheight, (int)ny + 1);
  591.       }
  592.  
  593.       if (dither == TRUE) {
  594.         flowTmp = bodyTmp;
  595.         for (ny = 0; ny < newheight; ny++) {
  596.           for (nx = 0; nx < newwidth; nx++) {
  597.             unsigned char palpix = *flowDst++ = MatchD(flowTmp, Palette);
  598.             PRECISION_EXT fR, fG, fB;
  599.  
  600. #define MakeError(offset, errorR, errorG, errorB) ({ \
  601.   PRECISION_EXT new; \
  602.   new = (PRECISION_EXT)(flowTmp[offset].r) + (errorR); \
  603.   if(new > 255) \
  604.     new = 255; \
  605.   else if(new < 0) \
  606.     new = 0; \
  607.   flowTmp[offset].r = (PRECISION)new; \
  608.   new = (PRECISION_EXT)(flowTmp[offset].g) + (errorG); \
  609.   if(new > 255) \
  610.     new = 255; \
  611.   else if(new < 0) \
  612.     new = 0; \
  613.   flowTmp[offset].g = (PRECISION)new; \
  614.   new = (PRECISION_EXT)(flowTmp[offset].b) + (errorB); \
  615.   if(new > 255) \
  616.     new = 255; \
  617.   else if(new < 0) \
  618.     new = 0; \
  619.   flowTmp[offset].b = (PRECISION)new; })
  620.  
  621.             /*
  622.              * calculate error *
  623.              *      erro,7/16
  624.              * 3/16,5/16,1/16
  625.              */
  626.             fR = ((PRECISION_EXT)(Palette[(short int)palpix].r) - (PRECISION_EXT)(flowTmp->r)) / FS_SCALE;
  627.             fG = ((PRECISION_EXT)(Palette[(short int)palpix].g) - (PRECISION_EXT)(flowTmp->g)) / FS_SCALE;
  628.             fB = ((PRECISION_EXT)(Palette[(short int)palpix].b) - (PRECISION_EXT)(flowTmp->b)) / FS_SCALE;
  629.             if((fR + fG + fB) != 0) {
  630.               if ((ny + 1) < newheight) {
  631.              if ((nx - 1) > 0) {
  632.               MakeError((newwidth - 1), (fR * 3), (fG * 3), (fB * 3));
  633.             }
  634.             MakeError((newwidth), (fR * 5), (fG * 5), (fB * 5));
  635.             if ((nx + 1) < newwidth) {
  636.               MakeError((newwidth + 1), (fR), (fG), (fB));
  637.             }
  638.               }
  639.               if ((nx + 1) < newwidth) {
  640.             MakeError((1), (fR * 7), (fG * 7), (fB * 7));
  641.               }
  642.             }
  643.  
  644.             flowTmp++;
  645.           }
  646.           mprogress((int)newheight, (int)ny + 1);
  647.         }
  648.       }
  649.         }
  650.  
  651.     if (dither == TRUE)
  652.           tfree(bodyTmp);
  653.       }
  654.       else
  655.         eprintf("cannot tmalloc %d bytes for picture\n", picType == TYPE_PPM ? newwidth * newheight * 3 : newwidth * newheight);
  656.  
  657.       tfree(bodySrc);
  658.     }
  659.     else
  660.       eprintf("cannot tmalloc %d bytes for picture\n", picType == TYPE_PPM ? width * height * 3 : width * height);
  661.   }
  662.   else
  663.     eprintf("unknown picture-type\n");
  664.  
  665.   return Picture;
  666. }
  667.